/*

Gamebots UT Copyright (c) 2002, Andrew N. Marshal, Gal Kaminka
Gamebots UT 2003/2004 port Copyright (c) 2005
       Joe Manojlovich, Tim Garwood, Jessica Bayliss
Gamebots Pogamut derivation Copyright (c) 2007, Michal Bida
	- derived mainly from 2002 Marshal, Kaminka version

All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

This software must also be in compliance with the Epic Games Inc. license for mods which states the following: "Your mods must be distributed solely for free, period. Neither you, nor any other person or party, may sell them to anyone, commercially exploit them in any way, or charge anyone for receiving or using them without prior written consent of Epic Games Inc. You may exchange them at no charge among other end-users and distribute them to others over the Internet, on magazine cover disks, or otherwise for free." Please see http://www.epicgames.com/ut2k4_eula.html for more information.

*/

//=============================================================================
// BotConnection.
// Based connection class
//=============================================================================
class BotConnection extends GBClientClass;

//------------Variables---------------------------

// delay between visionUpdates
var config float visionTime;

// on / off all synchronous messages
var config bool bSynchronousMessagesOff;

//used to store info inside function where local wont work
//set property text dosent seem to work with a local
var bool tempBool;

var() class<pickup> tempInventory;

var() class<SpeciesType> TempSpecies;

// the one server and the actual bot we're in control of
var BotServer Parent;
var RemoteBot theBot;

struct CustomRay{
	var() config string Id;
	var() config rotator Rotation;
	var() config float Length;
	var() config bool FastTrace;
	var() config bool TraceActors;
	var() config TraceLine VisualizerMiss;
	var() config TraceLine VisualizerHit;
};

var FocusActorClass FocusActor;
//var Khepera Car2;
//var class<Khepera> Car1;
var Vehicle CarVehicle;
var() class<Vehicle> SpawnVec;

var array<CustomRay> CustomRayList;

var xUtil.PlayerRecord BotSkin;

//------------Events---------------------------

// triggered when a socket connection with the server is established
event Accepted()
{
	if(bDebug)
		log("Accepted BotConnection" @ self);

	if (bNewProtocol)
	{
		SendLine("HELLO BOT");
	}
	else
	{
		SendGameInfo();
	}
	if (BotDeathMatch(Level.Game).bPasswordProtected)
		gotoState('checkingPassword','Waiting');
	else
		gotoState('waiting','Waiting');
}
event Closed()
{
	Destroyed();
	Destroy();
}

event Destroyed()
{
	if ( theBot != None && theBot.Pawn != None )
	{
		theBot.SetLocation(theBot.Pawn.Location);
		theBot.Pawn.RemoteRole = ROLE_SimulatedProxy;
		theBot.Pawn.UnPossessed();
		theBot.Pawn.Destroy();
	}

	if (theBot != None)
	{
		theBot.Destroy();
	}

	if (FocusActor != None)
	{
		FocusActor.Destroy();
	}
}


//------------Functions---------------------------

function PostBeginPlay()
{
	Parent = BotServer(Owner);
	ib = Parent.ib;
	as = Parent.as;
	ae = Parent.ae;

	if(bDebug)
		log("Spawned BotConnection");
	SaveConfig();
}

//triggered when weve gotten ready message from client, we will send game nfo, all navpoints and all items in a map
function ExportStatus()
{

	SendGameInfo();
	ExportNavPoints();
	ExportInventory();
	//ExportInventory();
}

//Init recieved from client
function InitBot()
{
	local string clientName, className, temp, DesiredSkin;
	local int teamNum;
	local vector StartLocation;
	local rotator StartRotation;
	local float DesiredSkill, DesiredAccuracy;
	local bool ShouldLeadTarget;

	clientName = GetArgVal("Name");

	DesiredSkin = GetArgVal("Skin");

	className = GetArgVal("ClassName");
	//SetDefaultSkin();

	temp = GetArgVal("Team");
	if( temp != "" )
		teamNum = int(temp);
	else
		teamNum = 255;

	temp = GetArgVal("DesiredSkill");
	if (temp != "")
		DesiredSkill = float(temp);
	else
		DesiredSkill = -1; //that means deufault value will be used

   	temp = GetArgVal("DesiredAccuracy");
	if (temp != "")
		DesiredAccuracy = float(temp);
	else
		DesiredAccuracy = -1; //that means deufault value will be used

	temp = GetArgVal("ShouldLeadTarget");
	if (temp != "")
		ShouldLeadTarget = bool(temp);
	else
		ShouldLeadTarget = false;

	//SetDefaultSkin();
	// add the bot into the game
	theBot = BotDeathMatch(Level.Game).AddRemoteBot(
		self,
		clientName,
		teamNum,
		className,
		DesiredSkin,
		DesiredSkill,
		DesiredAccuracy,
		ShouldLeadTarget
	);

	//Here the spawning of the pawn is handled - after weve got controler created
	if(theBot != None)
	{
		if (GetArgVal("ManualSpawn")!="")
			theBot.bAutoSpawn = !bool(GetArgVal("ManualSpawn"));


		if (GetArgVal("AutoTrace")!="")
			theBot.bAutoTrace = bool(GetArgVal("AutoTrace"));

		if (theBot.bAutoTrace && CustomRayList.Length == 0)
		{
			AddDefaultRays();
		}

		FocusActor = Spawn(class'BotAPI.FocusActorClass',self,,,);
		FocusActor.bHidden = true;

		// for shooting at the location
		theBot.myTarget = Spawn(class'BotAPI.FocusActorClass',theBot,,,);
		theBot.myTarget.bHidden = true;

		SendNotifyConf();
		//FocusActor.Test();
        if (bDebug)
			log("Succesfully Added bot "$theBot);

		if ( GetArgVal("Location")!="" )
		{
        	ParseVector(StartLocation,"Location");

        	if ( GetArgVal("Rotation")!="" )
			{
				ParseRot(StartRotation,"Rotation");
				BotDeathMatch(Level.Game).SpawnPawn(theBot,StartLocation,StartRotation);
			}
			else
			{
				BotDeathMatch(Level.Game).SpawnPawn(theBot,StartLocation, );
			}
		}
		else
		{
			if ( GetArgVal("Rotation")!="" )
			{
				ParseRot(StartRotation,"Rotation");
				BotDeathMatch(Level.Game).SpawnPawn(theBot, ,StartRotation);
			}
		}

		if (theBot.Pawn != none)
			theBot.GotoState('StartUp', 'Begin');
		else
			theBot.GotoState('Dead', 'Begin');

		gotoState('monitoring','Running');
	}
	else
	{
		if (bDebug)
			log("In InitReceived() - Error adding bot");
	}

}

//dont look here, some testing stuff :-)
function DoTest()
{
	//GBxPawn(theBot.Pawn).SetSkin();
	GBxPawn(theBot.Pawn).Test();
	/*
	log(theBot.FindPathTowardNearest(class'NavigationPoint', ));
	for ( i=0; i<16; i++ )
	{
		log("RouteCache: "$i$" is "$theBot.RouteCache[i]);
	}
	*/


	//GBxPawn(theBot.Pawn).DrawLine(theBot.Pawn.Location,theBot.Pawn.Location + 200 * vector(theBot.Pawn.Rotation));
	//Player.InteractionMaster.AddInteraction("BotAPI.GBHUDInteraction", PC.Player);
	//Level.bPlayersOnly = !Level.bPlayersOnly;
	//ParseRot(r,"Rot");
	//theBot.FocalPoint = theBot.Pawn.Location + 500 * vector(r);
	//theBot.setRotation(r);
	//theBot.FinishRotation();
		   /*
	foreach DynamicActors(Class'Engine.Gameinfo', FoundGameInfo) // iterates though all dynamic actors that are 'gameinfos'
      {                                                    // and stores a ref to them in  FoundGameInfo
       if (FoundGameInfo.bAllowVehicles == false)
           FoundGameInfo.bAllowVehicles = True;           // Sets the value FoundGameInfo.bAllowVehicles to true

        }
	SpawnVec = class<Khepera>(DynamicLoadObject("BotAPI.Khepera", class'Class'));
	CarVehicle = Spawn (SpawnVec, theBot,,theBot.Pawn.Location + 500 * vector(theBot.Pawn.rotation),);
		  */
	//Spawn(class<RotMover>(DynamicLoadObject("BotAPI.RotMover",class'Class')),theBot,,theBot.Pawn.Location + 500 * vector(theBot.Pawn.rotation),);
	//Cannot do this - movers have to be spawned not dynamically
}

function DrawTraceLine(int i, vector LineStart, vector LineEnd, bool LineHit)
{
	local Controller C;

    for( C = Level.ControllerList; C != None; C = C.NextController)
	{
		if( C.IsA('GBxPlayer') )
		{
			GBxPlayer(C).DrawTraceLine(LineStart,LineEnd,LineHit);
    	}//end if

	}                    /*
	if ((theBot.Pawn != none) && (theBot.Pawn.IsA('GBxPawn')))
	{
		GBxPawn(theBot.Pawn).DrawTraceLine(i,LineEnd,LineHit);
	}                      */
}

function bool LaunchRay (
	vector From,
	vector RealRayDirection, //current bot rotation
	CustomRay Ray,
	out vector To,
	out optional vector HitNormal,
	out optional vector HitLocation,
	out optional string HitId
	)
{
	local Actor HitActor; //shouldnt be object?

	To = From + (RealRayDirection * Ray.Length);
	HitId = "None";

	if (Ray.FastTrace == true)
	{
		return !FastTrace(To, From);
	}
	else
	{
		HitActor = Trace(HitLocation, HitNormal, To, From, Ray.TraceActors);
		if ( (HitActor != None) && HitActor.IsA('Pawn'))
			HitId = Pawn(HitActor).Controller $ Pawn(HitActor).Controller.PlayerReplicationInfo.PlayerID;
		else
			HitId = string(HitActor);
		if (HitActor != None)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
}

function AddCustomRay(string Id, vector Direction, float Length, bool FastTrace, bool TraceActors)
{
	local CustomRay Ray;
	local int i;
	local bool found;

	found = false;
	for (i=0; i < CustomRayList.Length; i++)
	{
		if (CustomRayList[i].Id == Id)
		{
			found = true;
			break;
		}
	}

	if (found)
	{
		CustomRayList[i].Rotation = rotator(Direction);
		CustomRayList[i].Length = Length;
		CustomRayList[i].FastTrace = FastTrace;
		CustomRayList[i].TraceActors = TraceActors;
		//We have to update emmiters - we'll destroy them, they will be recreated with correct info
		if (CustomRayList[i].VisualizerMiss != none)
			CustomRayList[i].VisualizerMiss.Destroy();
		if (CustomRayList[i].VisualizerHit != none)
			CustomRayList[i].VisualizerHit.Destroy();
	}
	else
	{
		Ray.Id = Id;
		Ray.Rotation = rotator(Direction);
		Ray.Length = Length;
		Ray.FastTrace = FastTrace;
		Ray.TraceActors = TraceActors;

		CustomRayList[CustomRayList.Length] = Ray;
	}
}

function RemoveCustomRay(string Id)
{
	local int i,j, CustomRayListLength;
	local bool found;

	if (Id == "All")
	{
		//destroy the visualizers
		for ( i=0; i < CustomRayList.Length; i++ )
		{
			if (CustomRayList[i].VisualizerMiss != none)
				CustomRayList[i].VisualizerMiss.Destroy();
			if (CustomRayList[i].VisualizerHit != none)
				CustomRayList[i].VisualizerHit.Destroy();
		}

		CustomRayList.Length = 0;
		return;
	}

	found = false;
	CustomRayListLength = CustomRayList.Length;
	log ("Length before removing "$CustomRayList.Length);
	i = 0;
	while (i < CustomRayListLength)
	{
		if (CustomRayList[i].Id == Id)
		{
			found = true;
			if (CustomRayList[i].VisualizerMiss != none)
				CustomRayList[i].VisualizerMiss.Destroy();
			if (CustomRayList[i].VisualizerHit != none)
				CustomRayList[i].VisualizerHit.Destroy();
			break;
		}
		i++;
	}

	for ( j=i; j < (CustomRayListLength - 1); j++ )
	{
		CustomRayList[j] = CustomRayList[j+1];
	}

	if (found)
		CustomRayList.Length = CustomRayListLength - 1;
		/*
	log ("Length after removing "$CustomRayList.Length);
	log ("ID of last obj in list "$CustomRayList[CustomRayListLength - 2].Id);
	log ("ID of deleted obj in list "$CustomRayList[CustomRayListLength - 1].Id);
	*/
}

function AddDefaultRays()
{
	local CustomRay Ray;

	CustomRayList.Length = 0; //delete all rays from list

	Ray.Id = "StraightAhead";
	Ray.Rotation = rotator(vect(1,0,0));
	Ray.Length = 250;
	Ray.FastTrace = false;
	Ray.TraceActors = false;

	CustomRayList[0] = Ray;

	Ray.Id = "45toLeft";
	Ray.Rotation = rotator(vect(1,-1,0));
	Ray.Length = 200;
	Ray.FastTrace = false;
	Ray.TraceActors = false;

	CustomRayList[1] = Ray;

	Ray.Id = "45toRight";
	Ray.Rotation = rotator(vect(1,1,0));
	Ray.Length = 200;
	Ray.FastTrace = false;
	Ray.TraceActors = false;

	CustomRayList[2] = Ray;
}

function AutoTrace()
{
	local vector from, to, RealRayDirection;
	local bool result;
	local vector hitNormal, hitLocation;
	local string hitId;
	local int i, CustomRayListLength;
	local vector FloorNormal, FloorLocation;

	if (theBot.Pawn == None)
		return;


	//we have to take into account also angle of the floor we are standing on
	FloorNormal = vect(0,0,0);
	//Trace(FloorLocation,FloorNormal,theBot.Pawn.Location + vect(0,0,-100),theBot.Pawn.Location, false, ,);

	i = 0;
	CustomRayListLength = CustomRayList.Length;
	while ((i < CustomRayListLength) && (theBot.Pawn != None))
	{
		from = theBot.Pawn.Location;

		RealRayDirection = vector(theBot.Pawn.Rotation + CustomRayList[i].Rotation);
		//TODO: Fix this cause. Cause that z-axis of rays is ignored.
		//RealRayDirection += FloorNormal * (Normal(RealRayDirection) dot FloorNormal) * -1;

		result = LaunchRay(from, RealRayDirection, CustomRayList[i], to, hitNormal, hitLocation, hitId );
		if (theBot.bDrawTraceLines)
		{
			if (theBot.Pawn != none )
			{
				if (CustomRayList[i].VisualizerHit == none)
				{
					CustomRayList[i].VisualizerHit = Spawn(class'BotAPI.TraceLineRed', theBot.Pawn,, theBot.Pawn.Location, theBot.Pawn.Rotation);
					CustomRayList[i].VisualizerHit.Instigator = theBot.Pawn;
					theBot.Pawn.AttachToBone(CustomRayList[i].VisualizerHit, 'spine');
   					CustomRayList[i].VisualizerHit.BeamDirection = CustomRayList[i].Rotation;
   					CustomRayList[i].VisualizerHit.BeamLength = CustomRayList[i].Length;
   					CustomRayList[i].VisualizerHit.LifeSpan = Level.Game.TimeLimit * 60;
				}

   				if (CustomRayList[i].VisualizerMiss == none)
   				{
					CustomRayList[i].VisualizerMiss = Spawn(class'BotAPI.TraceLineGreen', theBot.Pawn,, theBot.Pawn.Location, theBot.Pawn.Rotation);
					CustomRayList[i].VisualizerMiss.Instigator = theBot.Pawn;
					theBot.Pawn.AttachToBone(CustomRayList[i].VisualizerMiss, 'spine');
   					CustomRayList[i].VisualizerMiss.BeamDirection = CustomRayList[i].Rotation;
   					CustomRayList[i].VisualizerMiss.BeamLength = CustomRayList[i].Length;
   					CustomRayList[i].VisualizerMiss.LifeSpan = Level.Game.TimeLimit * 60;
				}

				if (result) //use red
				{
					CustomRayList[i].VisualizerMiss.bHidden = true;
					CustomRayList[i].VisualizerHit.bHidden = false;
				}
				else //use green
				{
					CustomRayList[i].VisualizerMiss.bHidden = false;
					CustomRayList[i].VisualizerHit.bHidden = true;
   				}

			}
		}
		SendLine("ATR {Id " $ CustomRayList[i].Id $
			"} {From " $ from $
			"} {To " $ to $
			"} {FastTrace " $ CustomRayList[i].fastTrace $
			"} {Result " $ result $
			"} {HitNormal " $ hitNormal $
			"} {HitLocation " $ hitLocation $
			"} {TraceActors " $ CustomRayList[i].traceActors $
			"} {HitId " $ hitId $
			"}");
		i++;
	}

}
function SendNotifyConf()
{
	local string outstring;

	outstring = "CONFCH {Id " $ theBot $ theBot.PlayerReplicationInfo.PlayerID $
		"} {ManualSpawn " $ !theBot.bAutoSpawn $
		"} {AutoTrace " $ theBot.bAutoTrace $
		"} {Invulnerable " $ theBot.bGodMode $
		"} {Name " $ theBot.PlayerReplicationInfo.PlayerName $
		"} {VisionTime " $ theBot.myConnection.VisionTime $
		"} {ShowDebug " $ theBot.bDebug $
		"} {ShowFocalPoint " $ theBot.bShowFocalPoint $
		"} {DrawTraceLines " $ theBot.bDrawTraceLines $
		"} {SynchronousOff " $ theBot.myConnection.bSynchronousMessagesOff $
		"}";

	//notify that variables changed
	SendLine(outstring);

	//notify all control servers that variables changed
	GlobalSendLine(outstring,true,false);
}

function SendNotifyPause ( bool bGamePaused )
{
	local Controller C;
	local GBClientClass G;

	for(C = Level.ControllerList; C != None; C = C.NextController )
	{
		if( C.IsA('RemoteBot') )
		{
			if (bGamePaused)
				RemoteBot(C).myConnection.SendLine("PAUSED");
			else
				RemoteBot(C).myConnection.SendLine("RESUMED");
		}
	}

    if (BotDeathMatch(Level.Game).theControlServer != None)
	{
		for (G = BotDeathMatch(Level.Game).theControlServer.ChildList; G != None; G = G.Next )
		{
			if (bGamePaused)
				G.SendLine("PAUSED");
			else
				G.SendLine("RESUMED");
		}
	}
}

//Main function for processing commands
function ProcessAction(string cmdType)
{
	if(bDebug)
		log("comandType:"@cmdType);

	if (bIterative)
		Level.Pauser = None;

	if (IsInState('checkingPassword'))
	{
		switch(cmdType)
		{
			case "PASSWORD":
				ReceivedPassword();
			break;
			case "READY":
				ReceivedReady();
			break;
		}
	}
	else
	{
		switch(cmdType)
		{
			case "ADDINV":
				ReceivedAddInv();
			break;
			case "ADDRAY":
				ReceivedAddRay();
			break;
			case "CHANGETEAM":
				ReceivedChangeTeam();
			break;
			case "CHANGEWEAPON":
				ReceivedChangeWeapon();
			break;
			case "CHATRR":
				ReceivedChAtrr();
			break;
			case "CHECKREACH":
				ReceivedCheckReach();
			break;
			case "CMOVE":
				ReceivedCMove();
			break;
			case "CONF":
				ReceivedConf();
			break;
			case "COMBO":
				ReceivedCombo();
			break;
			case "DODGE":
				ReceivedDodge();
			break;
			case "FTRACE":
				ReceivedFTrace();
			break;
			case "GETINVS":
				ExportInventory();
			break;
			case "GETNAVS":
				ExportNavPoints();
			break;
			case "GETPATH":
				ReceivedGetPath();
			break;
			case "GIVEINV":
				ReceivedGiveInv();
			break;
			case "INCH":
				ReceivedInch();
    		break;
    		case "INIT":
				ReceivedInit();
			break;
			case "JUMP":
				ReceivedJump();
			break;
			case "MESSAGE":
				ReceivedMessage();
			break;
			case "MOVE":
				ReceivedMove();
			break;
			case "PAUSE":
				ReceivedPause();
			break;
			case "PING":
				SendLine("Pong");
			break;
			case "QUIT":
				Closed();
			break;
			case "READY":
				ReceivedReady();
			break;
			case "REC":
				ReceivedRec();
			break;
			case "REMOVERAY":
				ReceivedRemoveRay();
			break;
			case "RESPAWN":
				ReceivedRespawn();
			break;
			case "ROTATE":
				ReceivedRotate();
			break;
			case "RUNTO":
				ReceivedRunTo();
			break;
			case "SETCROUCH":
				ReceivedSetCrouch();
			break;
			case "SETSKIN":
				ReceivedSetSkin();
			break;
    	    case "SETWALK":
				ReceivedSetWalk();
			break;
			case "SHOOT":
				ReceivedShoot();
			break;
			case "SPEECH":
				ReceivedSpeech(); //doesnt work right now
			break;
			case "STOP":
				ReceivedStop();
			break;
			case "STOPREC":
				ReceivedStopRec();
			break;
			case "STOPSHOOT":
				ReceivedStopShoot();
			break;
			case "STRAFE":
				ReceivedStrafe();
			break;
			case "TEST":
				DoTest();
			break;
			case "THROW":
				ReceivedThrow();
			break;
			case "TRACE":
				ReceivedTrace();
			break;
			case "TURNTO":
				ReceivedTurnTo();
			break;
		}//end switch
	}//end if
}

function ReceivedAddInv()
{
	local string target;

	if ((bAllowCheats != True) || theBot == None || theBot.Pawn == None)
		return;

	target = GetArgVal("Class");
	target = "class'"$target$"'";
	setPropertyText("tempInventory",target);
	//log("Added inventory will be "$tempInventory);
	if (tempInventory != None)
		theBot.SpawnInventory(tempInventory);

}

function ReceivedAddRay()
{
	local string target;
	local float floatNumber;
	local vector v;
	local bool boolResult, boolResult2;

	target = GetArgVal("Id");

	if (target == "Default")
	{
		AddDefaultRays();
	}
	else
	{
		ParseVector(v,"Direction");
		floatNumber = float(GetArgVal("Length"));
		boolResult = bool(GetArgVal("FastTrace"));
		boolResult2 = bool(GetArgVal("TraceActors"));
		AddCustomRay(target,v,floatNumber,boolResult,boolResult2);
	}

}

function ReceivedChangeTeam()
{
	local string temp;

	if ((theBot != none) && Level.Game.IsA('BotTeamGame'))
	{
		temp = GetArgVal("Team");
		if (temp != "")
		{
	    	if (BotTeamGame(Level.Game).ChangeTeam(theBot, int(temp), true))
			{
				SendLine("TEAMCHANGE"$ib$as$"Success"$ib$"True"$ae$ib$as$"DesiredTeam"$ib$temp$ae);
			}
			else
			{
			    SendLine("TEAMCHANGE"$ib$as$"Success"$ib$"False"$ae$ib$as$"DesiredTeam"$ib$temp$ae);
			}
	    }
	}
}


function ReceivedChangeWeapon()
{
	local string Target;
	local Inventory Inv;
	local Weapon TargetWeapon;

    if (theBot == none || theBot.Pawn == None || theBot.Pawn.Inventory == None )
		return;

	Target = GetArgVal("Id");
	if( Target ~= "best" )
	{
		theBot.StopFiring();
		theBot.SwitchToBestWeapon();
	}
	else
	{
		TargetWeapon = none;
		for( Inv=theBot.Pawn.Inventory; Inv!=None; Inv=Inv.Inventory )
		{
			if (target == string(Inv))
			{
				if (Inv.IsA('Weapon'))
					TargetWeapon = Weapon(Inv);
				break;
			}
		}
		if (TargetWeapon == none)
			return;

        theBot.StopFiring();
		//log("Pawns Target Weapon "$TargetWeapon);
		//log("Pawns weapoin: "$theBot.Pawn.Weapon);
		theBot.Pawn.PendingWeapon = TargetWeapon;
		if ( theBot.Pawn.PendingWeapon == theBot.Pawn.Weapon )
			theBot.Pawn.PendingWeapon = None;
		if ( theBot.Pawn.PendingWeapon == None )
			return;

		//log("Strelba: "$theBot.bFire$" a alt fire "$theBot.bAltFire);
       	if ( theBot.Pawn.Weapon == None )
			theBot.Pawn.ChangedWeapon();
		else if ( theBot.Pawn.Weapon != theBot.Pawn.PendingWeapon )
			theBot.Pawn.Weapon.PutDown();


	}
}

function ReceivedChAtrr()
{
	local string target;

	if (theBot == None || theBot.Pawn == None )
		return;

	target = GetArgVal("Health");
	if (target != "")
	{
		theBot.SetHealth(int(target));
	}

	target = GetArgVal("Adrenaline");
	if (target != "")
	{
		theBot.SetAdrenaline(int(target));
	}


}

function ReceivedCheckReach()
{
	local Controller C;
	local string target, id;
	local vector v;
	local bool boolResult;

	if (theBot == None || theBot.Pawn == None)
		return;

	target = GetArgVal("Target");
	id = GetArgVal("Id");
	if(target == "")
	{
		ParseVector(v,"Location");
		boolResult = theBot.PointReachable(v);
		sendLine("RCH" $ib$as$ "Id" $ib$ id $ae$ib$as$ "Reachable" $ib$ boolResult
		$ae$ib$as$ "From" $ib$ theBot.Pawn.Location $ae);
	}
	else
	{
		for(C = Level.ControllerList; C != None; C = C.NextController )
		{
			if( ( C $ C.PlayerReplicationInfo.PlayerID ) == target )
			{
				break;
			}
		}
		if (C != None)
		{
			boolResult = theBot.actorReachable( C.Pawn );
			sendLine("RCH" $ib$as$ "Id" $ib$ id $ae$ib$as$ "Reachable" $ib$ boolResult
			$ae$ib$as$ "From" $ib$ theBot.Pawn.Location $ae$ib$as$ "To" $ib$ C.Pawn.Location $ae);
		}
		else
		{
			SetPropertyText("tempActor",target);
			if (tempActor != None)
			{
				boolResult = theBot.actorReachable( tempActor );
				sendLine("RCH" $ib$as$ "Id" $ib$ id $ae$ib$as$ "Reachable" $ib$ boolResult
				$ae$ib$as$ "From" $ib$ theBot.Pawn.Location $ae$ib$as$ "To" $ib$ tempActor.Location $ae);
			}
		}
	}

}

function ReceivedCMove()
{
	local float Speed;

	if (theBot == None || theBot.Pawn == None)
		return;

	Speed = float(GetArgVal("Speed"));
	if ( (Speed >= 0.1) && (Speed <= theBot.MaxSpeed) )
		theBot.Pawn.GroundSpeed = Speed * theBot.Pawn.Default.GroundSpeed;

	theBot.GotoState('StartUp','MoveContinuous');
}

function ReceivedFTrace()
{
	local vector v,v2;
	local string target;

	if (theBot == None || theBot.Pawn == None)
		return;

	if (GetArgVal("From") == "")
	{
		if (theBot.Pawn != None)
			v = theBot.Pawn.Location;
		else
			return;

	}
	else
	{
		ParseVector(v,"From");
	}
	if (GetArgVal("To") == "")
	{
		return;
	}

	ParseVector(v2,"To");
	target = GetArgVal("Id");

	SendLine("FTR" $ib$as$ "Id" $ib$ target $ae$ib$as$
				"From" $ib$ v $ae$ib$as$
				"To" $ib$ v2 $ae$ib$as$
				"Result" $ib$ !FastTrace(v2,v) $ae);
}

function ReceivedCombo()
{
	local string tmp;

	if (theBot == None)
		return;

	tmp = GetArgVal("Type");
	if (tmp != "")
		theBot.RemoteCombo(tmp);

}


function ReceivedConf()
{
	local float floatNumber;
	local string target;
	local int i;

	if (theBot == none)
		return;

	if (GetArgVal("AutoTrace") != "")
		theBot.bAutoTrace = bool(GetArgVal("AutoTrace"));
	if (GetArgVal("DrawTraceLines") != "")
	{
		theBot.bDrawTraceLines = bool(GetArgVal("DrawTraceLines"));

		if (!theBot.bDrawTraceLines)
		{
			//Need to change the settings of already spawned rays
			for (i = 0; i < CustomRayList.Length;i++)
			{
				if (CustomRayList[i].VisualizerMiss != none)
				{
                 	CustomRayList[i].VisualizerMiss.bHidden = true;
				}
				if (CustomRayList[i].VisualizerHit != none)
				{
                	CustomRayList[i].VisualizerHit.bHidden = true;
				}
			}
		}
	}
	if (GetArgVal("ManualSpawn") != "")
		theBot.bAutoSpawn = !bool(GetArgVal("ManualSpawn"));
	if (GetArgVal("ShowFocalPoint")!="")
		theBot.bShowFocalPoint = bool(GetArgVal("ShowFocalPoint"));
	if (GetArgVal("ShowDebug")!="")
		theBot.bDebug = bool(GetArgVal("ShowDebug"));
	if (GetArgVal("Name") != "")
	{
		target = GetArgVal("Name");
		theBot.PlayerReplicationInfo.PlayerName = target;
		Level.Game.changeName( theBot, target, true );
	}
	if ((GetArgVal("Invulnerable") != "") && (bAllowCheats == true))
		theBot.bGodMode = bool(GetArgVal("Invulnerable"));
	if (GetArgVal("VisionTime") != "")
	{
		floatNumber = float(GetArgVal("VisionTime"));
		if ((floatNumber >= 0.1) && (floatNumber <= 2))
			visionTime = floatNumber;
	}
	if (GetArgVal("SynchronousOff") != "")
	{
		theBot.myConnection.bSynchronousMessagesOff = bool(GetArgVal("SynchronousOff"));
	}
	SendNotifyConf();

}



function ReceivedDodge()
{
	local string temp;
	local vector vec;

	if (theBot == none || theBot.Pawn == none)
		return;

	temp = GetArgVal("Direction");
	if (temp != "")
	{
		ParseVector(vec,"Direction");
		GBxPawn(theBot.Pawn).RemoteDoDodge(Normal(vector(theBot.Pawn.Rotation + rotator(vec))));
	}

}

function ReceivedGetPath()
{
	local vector v;
	local string outBuf, id;
	local int i;

	if ( theBot == None )
		return;

	//clear the old path
	for ( i=0; i<16; i++ )
	{
		if ( theBot.RouteCache[i] == None )
			break;
		else
		{
			theBot.RouteCache[i] = None;
		}
	}
	ParseVector(v,"Location");
	theBot.FindPathTo(v);
	id = GetArgVal("id");
	outBuf = "PTH"$ib$as$"Id"$ib$id$ae;
	for ( i=0; i<16; i++ )
	{
		if ( theBot.RouteCache[i] == None )
			break;
		else
		{
			outBuf = outBuf$ib$as$i$ib$theBot.RouteCache[i]$ib$theBot.RouteCache[i].Location$ae;
		}
	}
	SendLine(outBuf);

}

function ReceivedGiveInv()
{
	local Controller C;
	local string target;
	local Inventory Inv;

	if ((theBot == None) || (theBot.Pawn == None))
		return;

	target = GetArgVal("Target");

	for(C = Level.ControllerList; C != None; C = C.NextController )
		{
		if( (C$C.PlayerReplicationInfo.PlayerID) == target )
		{
			if (C.Pawn != none)
			{
			 	target = GetArgVal("ItemId");
			 	Inv = none;
				for( Inv=theBot.Pawn.Inventory; Inv!=None; Inv=Inv.Inventory )
				{
					if (String(Inv) == target)
						break;
				}
				if (Inv != none)
				{
					if (theBot.Pawn.Weapon == Inv)
						return;
					if (C.Pawn.AddInventory(Inv))
					{
						SendLine("LIN"$ib$as$"Id"$ib$Inv$ae);
					 	theBot.Pawn.DeleteInventory( Inv );
					}
				}
			}
       	}

	}

}

function ReceivedInch()
{
	//test function
	/* must deal with target, focus and destination */
	theBot.StopWaiting();
	theBot.myDestination = (100 * vector(theBot.Pawn.Rotation)) + theBot.Pawn.Location;
	theBot.GotoState('Startup', 'MoveToPoint');
}

function ReceivedInit()
{
	if (IsInState('waiting'))
	{
		InitBot();
	}
	else
	{
		if (bDebug)
			log("Bot already spawned");
	}
}

function ReceivedJump()
{
	local string tmp;
	local float floatNumber;
	local bool bDouble;

	if (theBot == None || theBot.Pawn == None)
		return;

	bDouble = false;
	tmp = GetArgVal("DoubleJump");
	if (tmp != "")
		bDouble = bool(tmp);
	floatNumber = float(GetArgVal("JumpZ"));

	theBot.RemoteJump(bDouble, floatNumber);

}


function ReceivedMessage()
{
	local string target;
	local bool boolResult;

	if (theBot == None )
		return;

	//Note - currently only allow messages under 256 chars
	target = GetArgVal("Text");
	boolResult = bool(GetArgVal("Global"));
	if(target != "")
	{
		// @ preceding message makes it global. dont ask. not my code
		if(boolResult)
		{
			theBot.RemoteBroadcast("@"$target);
		}
		else
		{
			theBot.RemoteBroadcast(target);
		}
	}

}

function ReceivedMove()
{
	local float Speed;
	local vector v,v2;

	if (theBot == None || theBot.Pawn == None)
		return;

	Speed = float(GetArgVal("Speed"));
	if ( (Speed >= 0.1) && (Speed <= theBot.MaxSpeed) )
		theBot.Pawn.GroundSpeed = Speed * theBot.Pawn.Default.GroundSpeed;

	ParseVector(v,"Location1");
	ParseVector(v2,"Location2");

	//We have commented these lines so turn commands won't be interrupted
	//testing needed
	//theBot.FocalPoint = v;
	theBot.myFocalPoint = v;
	theBot.myDestination = v;
	theBot.Destination = v;
	theBot.pendingDestination = v2;

	theBot.GotoState('StartUp','MoveAlong');

}

function ReceivedPause()
{
	local bool bWasPaused;

	if ((!bAllowPause) || theBot == None)
		return;

	if ((Level.bPlayersOnly == true) || (Level.Pauser != none))
		bWasPaused = true;
	else
		bWasPaused = false;


	if (GetArgVal("PauseBots")!="")
	{
		Level.bPlayersOnly = bool(GetArgVal("PauseBots"));
	}
	if (GetArgVal("PauseAll")!="")
	{
		if (bool(GetArgVal("PauseAll")))
		{
			if (Level.Pauser == None)
			{
				// we have to blame the pause on somebody
				Level.Pauser = BotDeathMatch(Level.Game).LevelPauserFeed;
			}
		}
		else
		{
			Level.Pauser = None;
		}

	}

	if (bWasPaused == true)
	{
		if ((Level.bPlayersOnly == false) && (Level.Pauser == none))
			SendNotifyPause(false); //send resume message
	}
	else
	{
		if ((Level.bPlayersOnly == true) || (Level.Pauser != none))
			SendNotifyPause(true); //send pause message
	}

}

function ReceivedPassword()
{
	local string target;

	target = GetArgVal("Password");

	if (target == BotDeathMatch(Level.Game).Password)
	{
		SendLine("PASSWDOK");
		ExportStatus();
		gotoState('waiting','Waiting');
	}
	else
	{
		SendLine("PASSWDWRONG");
		Closed();
	}

}


function ReceivedReady()
{
	if (IsInState('waiting'))
		ExportStatus();

	if ( IsInState('checkingPassword') )
		SendLine("PASSWORD"$ib$as$
			"BlockedByIP" $ib$ BotDeathMatch(Level.Game).PasswordByIP $ae);

}

function ReceivedRec()
{
	local string target;

	target = GetArgVal("FileName");
	ConsoleCommand("demorec "$target, True);
	SendLine("RECSTART");
}

function ReceivedRemoveRay()
{
	local string target;

	if (theBot == None)
		return;
	target = GetArgVal("Id");
	RemoveCustomRay(target);
}

function ReceivedRespawn()
{
	local vector v;
	local rotator r;

	if ( theBot == None )
		return;

	ParseVector(v,"StartLocation");
	ParseRot(r,"StartRotation");
	theBot.RespawnPlayer(v,r);
}

function ReceivedRotate()
{
	local string target;
	local rotator r;
	local int i;

	if (theBot.Pawn == None)
		return;

	target = GetArgVal("Axis");
	r = theBot.Rotation;
	i = int(GetArgVal("Amount"));
	if(target == "Vertical")
	{
		r.Pitch = int(theBot.Pawn.ViewPitch) * 65556/255 + i;
		//r.Yaw = theBot.Pawn.Rotation.Yaw;
	}
	else
	{
		r.Pitch = int(theBot.Pawn.ViewPitch) * 65556/255;
		r.Yaw += i;
	}

	theBot.myFocalPoint = theBot.Pawn.Location + ( vector(r) * 500);
	theBot.FocalPoint = theBot.myFocalPoint;
	theBot.myFocus = None;
	theBot.Focus = None; //theBot.Pawn.Location + ( vector(r) * 1000);

	//Not used - so turn commands won't interupt turning
	//theBot.StopWaiting();
	//theBot.GotoState('Startup', 'Turning');

}

function ReceivedRunTo()
{
	local float Speed;
	local string target;
	local vector v;

	if (theBot == None || theBot.Pawn == None)
		return;

	Speed = float(GetArgVal("Speed"));
	if ( (Speed >= 0.1) && (Speed <= theBot.MaxSpeed) )
		theBot.Pawn.GroundSpeed = speed * theBot.Pawn.Default.GroundSpeed;

	target = GetArgVal("Target");
	if(target == "")
	{
		ParseVector(v,"Location");
    	theBot.myDestination = v;
		theBot.Destination = v;
		//We have commented this line so turn commands won't be interrupted
		//testing needed
		//theBot.FocalPoint = v;

		//theBot.Focus = None;
		//should reapir issue that the bot is turning after finishing moveto,
		//MoveTo will reset FocalPoint to actual bot position - this can cause unwanted turning
		theBot.myFocalPoint = v + 500 * vector(rotator(v - theBot.Pawn.Location));

		//log("Set Focal point before move "$theBot.FocalPoint$"Set Focus befor move "$theBot.Focus);
		//theBot.RemoteDestination = none;
		theBot.GotoState('Startup', 'MoveToPoint');
	}
	else
	{
		SetPropertyText("tempActor",target);

		//TODO: Is all the trace controlling necessary?
		if( tempActor != None && theBot.LineOfSightTo(tempActor) )
		{
			theBot.MoveTarget = tempActor;

            //We have commented these lines so turn commands won't be interrupted
			//testing needed
			//theBot.FocalPoint = tempActor.Location;
			//theBot.Focus = None;

			theBot.myFocalPoint = tempActor.Location + 500 * vector(rotator(tempActor.Location - theBot.Pawn.Location)); //should reapir issue that the bot is turning after finishing moveto
			theBot.GotoState('Startup', 'MoveToActor');
		}
	}
}

function ReceivedSetCrouch()
{
	local string target;

	if (theBot == None || theBot.Pawn == None)
		return;

	target = GetArgVal("Crouch");
	SetPropertyText("tempBool",target);
	theBot.Pawn.ShouldCrouch( tempBool );

}

function ReceivedSetSkin()
{

	if (theBot == None)
		return;
	if (GetArgVal("Skin") != "")
	{

		//theBot.Pawn.LinkMesh(Mesh(DynamicLoadObject(GetArgVal("Skin"), class'Mesh')));
		theBot.DesiredSkin = GetArgVal("Skin");
		//theBot.Pawn.LinkMesh(Mesh(DynamicLoadObject(theBot.DesiredSkin, class'Mesh')));
	}
	theBot.RespawnPlayer();
}

function ReceivedSetWalk()
{

	local string target;

	if (theBot == None || theBot.Pawn == None)
		return;

	target = GetArgVal("Walk");
	SetPropertyText("tempBool",target);
	theBot.Pawn.bIsWalking = tempBool;

}

function ReceivedShoot()
{
	local rotator r;
	local string Target;
	local Controller C;
	local vector v;
	local bool targetLocked;

	if (theBot == None || theBot.Pawn == None)
		return;

	targetLocked = false;
	theBot.bTargetLocationLocked = false;
	Target = GetArgVal("Target");
	if( Target != "")
	{
		for( C=Level.ControllerList; C != None; C = C.NextController)
		{
			//We wont start shooting at non visible targets
			if( ((C $ C.PlayerReplicationInfo.PlayerID) == target) &&
				(C.Pawn != None) &&
				(theBot.LineOfSightTo(C.Pawn))
			)
			{
				//We will set desired bot as our enemy
				theBot.Focus = C.Pawn;
				theBot.myFocus = C.Pawn;
				theBot.Enemy = C.Pawn;
				theBot.RemoteEnemy = C;
				theBot.Target = C.Pawn;

				theBot.FocalPoint = C.Pawn.Location;
				theBot.myFocalPoint = C.Pawn.Location;
				targetLocked = true;
				break;
			}
		}
	}

	if (!targetLocked && GetArgVal("Location") != "")
	{
		ParseVector(v,"Location");

		theBot.myTarget.SetLocation(v);
		theBot.bTargetLocationLocked = true;

		//We are shooting at a location. We will set the FocalPoint
		theBot.FocalPoint = theBot.myTarget.Location;
		theBot.myFocalPoint = theBot.myTarget.Location;

		theBot.Focus = theBot.myTarget;
		theBot.Enemy = None;
		theBot.Target = theBot.myTarget;
	}

	theBot.RemoteFireWeapon(bool(GetArgVal("Alt")));
}

function ReceivedSpeech()
{
	local string target;

	if (theBot == None)
		return;

	target = GetArgVal("Text");
	theBot.TextToSpeech(target,50); //dont work dunno the reason, maybe volume bigger?
	SendLine(target);
}

function ReceivedStop()
{
	if (theBot == None || theBot.Pawn == None)
		return;

	theBot.GotoState('Startup', 'DoStop');
}

function ReceivedStopRec()
{
	ConsoleCommand("stopdemo", True);
	SendLine("RECEND");
}

function ReceivedStopShoot()
{
	if (theBot == None)
		return;

	theBot.StopWaiting();
	theBot.HaltFiring();
}

function ReceivedStrafe()
{
	local Controller C;
	local float Speed;
	local vector v,v2;
	local string focusTarg;

	if (theBot == None || theBot.Pawn == None)
		return;

	Speed = float(GetArgVal("Speed"));
	if ( (Speed >= 0.1) && (Speed <= theBot.MaxSpeed) )
		theBot.Pawn.GroundSpeed = Speed * theBot.Pawn.Default.GroundSpeed;

	ParseVector(v,"Location");
	theBot.myDestination = v;
	theBot.Destination = v;

	focusTarg = GetArgVal("Target");
	if(focusTarg == "")
	{
		ParseVector(v2,"Focus");
		theBot.Focus = FocusActor;
		FocusActor.SetLocation( v2 );
		theBot.myFocus = FocusActor;


		theBot.myFocalPoint = FocusActor.Location;
		theBot.FocalPoint = FocusActor.Location;

	}
	else
	{
		theBot.myFocus = None;
		for( C = Level.ControllerList; C != None; C = C.NextController)
		{
			if( (C$C.PlayerReplicationInfo.PlayerID) == focusTarg)
			{
				if( theBot.Pawn.LineOfSightTo(C.Pawn))
				{
					//point the bot at the location of the target
					theBot.FocalPoint = C.Pawn.Location;
					theBot.myFocalPoint = C.Pawn.Location;
					theBot.Focus = C.Pawn;
					theBot.myFocus = C.Pawn;
					theBot.Target = C.Pawn;

					break;
				}// end if
			}//end if

		}//end for
		if (theBot.myFocus == None)
		{
			setPropertyText("tempActor", focusTarg);
			if ((tempActor != none) && theBot.Pawn.LineOfSightTo(tempActor))
			{
				theBot.myFocus = tempActor;
				theBot.Focus = tempActor;
				theBot.myFocalPoint = tempActor.Location;
				theBot.FocalPoint = tempActor.Location;
			}
		}

	}//end else
	theBot.GotoState('Startup', 'Strafe');

}

function ReceivedThrow()
{
	local vector TossVel;

	if (theBot == None || theBot.Pawn == None)
		return;

	if (theBot.Pawn.CanThrowWeapon())
	{
		TossVel = Vector(theBot.GetViewRotation());
		TossVel = TossVel * ((theBot.Pawn.Velocity dot TossVel) + 500) + Vect(0,0,200);
		theBot.Pawn.TossWeapon(TossVel);
		theBot.SwitchToBestWeapon();
		SendLine("THROWN");
	}
}

function ReceivedTrace()
{
	local bool boolResult;
	local vector v, v2, HitLocation, HitNormal;
	local string target, string2;

	if (GetArgVal("From") == "")
	{
		if (theBot.Pawn != None)
			v = theBot.Pawn.Location;
		else
			return;

	}else
	{
		ParseVector(v,"From");
	}
	if (GetArgVal("To") == "")
	{
		return;
	}
	ParseVector(v2,"To");
	boolResult = bool(GetArgVal("TraceActors"));
	target = GetArgVal("Id");

	tempActor = Trace(HitLocation,HitNormal,v2,v,boolResult, , );
	if (tempActor == None)
		boolResult = false;
	else
		boolResult = true;
	if (tempActor.IsA('Pawn'))
		string2 = Pawn(tempActor).Controller $ Pawn(tempActor).Controller.PlayerReplicationInfo.PlayerID;
	else
		string2 = string(tempActor);

	SendLine("TRC" $ib$as$ "Id" $ib$ target $ae$ib$as$
				"From" $ib$ v $ae$ib$as$
				"To" $ib$ v2 $ae$ib$as$
				"Result" $ib$ boolResult $ae$ib$as$
				"HitId" $ib$ string2 $ae$ib$as$
				"HitLocation" $ib$ HitLocation $ae$ib$as$
				"HitNormal" $ib$ HitNormal $ae);

}

function ReceivedTurnTo()
{
	local Controller C;
	local vector v;
	local rotator r;
	local string target;

	if (theBot == none || theBot.Pawn == None)
		return;

	target = GetArgVal("Target");
	if(target == "")
	{
		ParseRot(r,"Rotation");
		if(r.Yaw == 0 && r.Pitch == 0 && r.Roll == 0)
		{
			//no target or rotation defined
			ParseVector(v,"Location");
			theBot.FocalPoint = v;
			theBot.myFocalPoint = v;
			//We erase possible focus actors
			theBot.myFocus = None;
			theBot.Focus = None;
		}
		else
		{
			//no target, yes rotation
			theBot.myFocalPoint = theBot.Pawn.Location + ( vector(r) * 500);
			theBot.FocalPoint = theBot.myFocalPoint;

			//We erase possible focus actors
			theBot.myFocus = None;
			theBot.Focus = None;

				}
	}
	else
	{
		//target defined

		//First we try to find if we should focus to a player or bot
		for(C = Level.ControllerList; C != None; C = C.NextController )
		{
			if( target == (C $ C.PlayerReplicationInfo.PlayerID) )
			{
				break;
			}
		}//end for
		if (C != None)
		{
			//Pawn must exists and must be visible
			if ((C.Pawn != None) && theBot.Pawn.LineOfSightTo(C.Pawn))
			{
				//We set the Controller as our target
				theBot.FocalPoint = C.Pawn.Location;
				theBot.myFocalPoint = C.Pawn.Location;
				theBot.Focus = C.Pawn;
				theBot.myFocus = C.Pawn;
				//TODO: This shouldn't be here - ruins our shoot command
				theBot.Target = C.Pawn;
			}
			else
			{
				return;
			}
		}
		else
		{
			tempActor = None;
			SetPropertyText("tempActor",target);
			//Actor must be visible
			if ((tempActor != None) && theBot.Pawn.LineOfSightTo(tempActor))
			{
				theBot.myFocus = tempActor;
				theBot.Focus = tempActor;
				theBot.myFocalPoint = tempActor.Location;
				theBot.FocalPoint = theBot.myFocalPoint;
			}
			else
			{
				return;
			}
		}
	}

    //Not used - so turn commands won't interupt turning
	//theBot.StopWaiting();
	//theBot.GotoState('Startup', 'Turning');

}

function SetDefaultSkin()
{
	BotSkin.Species = class'xGame.SPECIES_Egypt';
	BotSkin.MeshName = "HumanFemaleA.EgyptFemaleA";// mesh type?
	BotSkin.Skeleton = "HumanFemaleA.Skeleton_Female"; // custom skeleton if species default
	BotSkin.FaceSkinName = "PlayerSkins.EgyptFemaleAHeadA";
	BotSkin.BodySkinName = "PlayerSkins.EgyptFemaleABodyA";
	//BotSkin.Ragdoll =
	BotSkin.TeamFace = false;//bool
	BotSkin.Sex = "Female";
}

//TODO: Now this doesnt work - it is replication or something else?
function SetSkin()
{
	local string Target;

	if (GetArgVal("Species") != "")
	{
    	Target = GetArgVal("Species");
		Target = "class'"$target$"'";

		setPropertyText("TempSpecies",target);
		BotSkin.Species = TempSpecies;
	}
	if (GetArgVal("MeshName")!="")
		BotSkin.MeshName = GetArgVal("MeshName");
	if (GetArgVal("Skeleton")!="")
		BotSkin.Skeleton = GetArgVal("Skeleton");
	if (GetArgVal("FaceSkinName")!="")
		BotSkin.FaceSkinName = GetArgVal("FaceSkinName");
	if (GetArgVal("BodySkinName")!="")
		BotSkin.BodySkinName = GetArgVal("BodySkinName");
	if (GetArgVal("TeamFace")!="")
		BotSkin.TeamFace = bool(GetArgVal("TeamFace"));
	if (GetArgVal("Sex")!="")
		BotSkin.Sex = GetArgVal("Sex");
}

//Send a line to the client
function SendLine(string Text, optional bool bNoCRLF)
{
	if(bDebug)
		log("    Sending: "$Text);
	if(bNoCRLF)
		SendText(Text);
	else
		SendText(Text$Chr(13)$Chr(10));
}

//----------------- STATES

//Waiting state when connected
auto state waiting
{
Begin:
Waiting:
	sleep(5.0);
	goto 'Waiting';

}

state checkingPassword
{
Begin:
Waiting:
	sleep(5.0);
	goto 'Waiting';
}

state monitoring
{

Begin:
Running:
	if (bSynchronousMessagesOff)
		goto 'SynchronousOff';
	if(theBot != none && Level.Pauser == none && !theBot.IsInState('Dead') && !theBot.IsInState('GameEnded') )
	{
		//This is where synchronous batch messages are sent
		SendLine("BEG" $ib$as$ "Time" $ib$ Level.TimeSeconds $ae);
	/*	if (theBot.bDebug)
		{
			log("Measuring Time of synchronous batch: ");
			StopWatch(false);
		}*/

        SendLine( BotDeathMatch(Level.Game).GetGameStatus(theBot) );
		theBot.checkSelf();
		theBot.checkVision();

		// if bAutoTrace true, then send results of all rays
		if (theBot.bAutoTrace)
			AutoTrace();

	/*	if (theBot.bDebug)
		{
			StopWatch(true);
		}
	*/
		SendLine("END" $ib$as$ "Time" $ib$ Level.TimeSeconds $ae);
	}
	if (theBot.bDebug && !theBot.IsInState('StartUp'))
		log(theBot.getStateName());
	if (bIterative)
		Level.Pauser=theBot.PlayerReplicationInfo;

		sleep(visionTime);
	goto 'Running';
SynchronousOff:
	if (!bSynchronousMessagesOff)
		goto 'Running';
	sleep(1);
	goto 'SynchronousOff';
}


//-----------------

defaultproperties
{
     visionTime=0.250000
}
